﻿using System;
using System.Collections.Generic;
using System.Linq;
using Xenta.Entities;
using Xenta.Enums;
using Xenta.Security;
using Xenta.Utils;

namespace Xenta.Operations
{
    public class ImportCatalogTags : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("CTLG");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            var languages = uow.Execute(new SearchLanguages()).Result;

            foreach(var i in Objects)
            {
                if(!i.ContainsKey("EntityID") ||
                    !i.ContainsKey("Flags"))
                {
                    continue;
                }

                int entityID = i["EntityID"].ParseAs(0);
                var flags = i["Flags"].ParseAs<CatalogTagFlags>();
                CatalogTagEntity entity = null;

                if(entityID != 0)
                {
                    entity = uow.Execute(new UpdateCatalogTag
                    {
                        EntityID = entityID,
                        Flags = flags
                    }).Result;
                }
                else
                {
                    entity = uow.Execute(new CreateCatalogTag
                    {
                        Flags = flags
                    }).Result;
                }
                foreach(var l in languages.Where(x => i.ContainsKey(x.Code)))
                {
                    string name = i[l.Code];
                    if(String.IsNullOrWhiteSpace(name))
                        continue;

                    uow.Execute(new SaveCatalogTagTranslation
                    {
                        HolderID = entity.EntityID,
                        LanguageID = l.EntityID,
                        Name = name
                    });
                }
                result++;
            }
        }

        #endregion
    }

    public class ImportCatalogCategories : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("CTLG");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            var languages = uow.Execute(new SearchLanguages()).Result;

            foreach(var i in Objects)
            {
                if(!i.ContainsKey("EntityID") ||
                    !i.ContainsKey("Attributes") ||
                    !i.ContainsKey("Flags") ||
                    !i.ContainsKey("ParentID"))
                {
                    continue;
                }

                int entityID = i["EntityID"].ParseAs(0);
                int parentID = i["ParentID"].ParseAs(0);
                var attributeIDs = i["Attributes"].Split(new[]
                {
                    ','
                }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var flags = i["Flags"].ParseAs<CatalogCategoryFlags>();
                CatalogCategoryEntity entity = null;

                if(entityID != 0)
                {
                    entity = uow.Execute(new UpdateCatalogCategory
                    {
                        EntityID = entityID,
                        ParentID = parentID,
                        Flags = flags
                    }).Result;
                }
                else
                {
                    entity = uow.Execute(new CreateCatalogCategory
                    {
                        ParentID = parentID,
                        Flags = flags
                    }).Result;
                }
                foreach(var l in languages.Where(x => i.ContainsKey(x.Code)))
                {
                    string name = i[l.Code];

                    if(String.IsNullOrWhiteSpace(name))
                        continue;

                    uow.Execute(new SaveCatalogCategoryTranslation
                    {
                        HolderID = entity.EntityID,
                        LanguageID = l.EntityID,
                        Name = name
                    });
                }

                var oldAttributeIDs = entity.Attributes
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldAttributeIDs.Except(attributeIDs))
                {
                    uow.Execute(new UnmapLookupAttributeFromCatalogCategory
                    {
                        ChildID = j,
                        EntityID = entity.EntityID
                    });
                }
                foreach(var j in attributeIDs.Except(oldAttributeIDs))
                {
                    uow.Execute(new MapLookupAttributeToCatalogCategory
                    {
                        ChildID = j,
                        EntityID = entity.EntityID
                    });
                }

                result++;
            }
        }

        #endregion
    }

    public class ImportCatalogItemGroups : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("CTLG");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            var languages = uow.Execute(new SearchLanguages()).Result;

            foreach(var i in Objects)
            {
                if(!i.ContainsKey("EntityID") ||
                    !i.ContainsKey("Items") ||
                    !i.ContainsKey("Flags"))
                {
                    continue;
                }

                int entityID = i["EntityID"].ParseAs(0);
                int supplierID = i["SupplierID"].ParseAs(0);
                var itemIDs = i["Items"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var flags = i["Flags"].ParseAs<CatalogItemGroupFlags>();
                CatalogItemGroupEntity entity = null;

                if(entityID != 0)
                {
                    entity = uow.Execute(new UpdateCatalogItemGroup
                    {
                        EntityID = entityID,
                        Flags = flags
                    }).Result;
                }
                else
                {
                    entity = uow.Execute(new CreateCatalogItemGroup
                    {
                        SupplierID = supplierID,
                        Flags = flags
                    }).Result;
                }

                foreach(var l in languages.Where(x => i.ContainsKey(x.Code)))
                {
                    string name = i[l.Code];
                    if(String.IsNullOrWhiteSpace(name))
                        continue;
                    uow.Execute(new SaveCatalogItemGroupTranslation
                    {
                        HolderID = entity.EntityID,
                        LanguageID = l.EntityID,
                        Name = name
                    });
                }

                var oldItemIDs = entity.Items
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldItemIDs.Except(itemIDs))
                {
                    uow.Execute(new UnmapCatalogItemGroupFromCatalogItem
                    {
                        EntityID = j,
                        ChildID = entity.EntityID
                    });
                }
                foreach(var j in itemIDs.Except(oldItemIDs))
                {
                    uow.Execute(new MapCatalogItemGroupToCatalogItem
                    {
                        EntityID = j,
                        ChildID = entity.EntityID
                    });
                }

                result++;
            }
        }

        #endregion
    }

    public class ImportCatalogItems : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("CTLG");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            var languages = uow.Execute(new SearchLanguages()).Result;
            foreach(var i in Objects)
            {
                if(!i.ContainsKey("EntityID") ||
                    !i.ContainsKey("SupplierID") ||
                    !i.ContainsKey("Categories") ||
                    !i.ContainsKey("Groups") ||
                    !i.ContainsKey("Attributes") ||
                    !i.ContainsKey("Tags") ||
                    !i.ContainsKey("Flags"))
                {
                    continue;
                }

                int entityID = i["EntityID"].ParseAs(0);
                int supplierID = i["SupplierID"].ParseAs(0);
                var categoryIDs = i["Categories"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var groupIDs = i["Groups"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var attributeIDs = i["Attributes"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var tagIDs = i["Tags"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var flags = i["Flags"].ParseAs<CatalogItemFlags>();
                var entity = entityID == 0 ? null : uow.Execute(new GetCatalogItem
                {
                    EntityID = entityID
                }).Result;

                if(entity != null)
                {
                    entity = uow.Execute(new UpdateCatalogItem
                    {
                        EntityID = entity.EntityID,
                        SupplierID = supplierID,
                        FileGroupID = entity.FileGroup != null 
                            ? entity.FileGroup.EntityID 
                            : 0,
                        Flags = flags
                    }).Result;
                }
                else
                {
                    entity = uow.Execute(new CreateCatalogItem
                    {
                        FileGroupID = 0,
                        SupplierID = supplierID,
                        Flags = flags
                    }).Result;
                }

                foreach(var l in languages.Where(x => i.ContainsKey(x.Code)))
                {
                    string name = i[l.Code];
                    if(String.IsNullOrWhiteSpace(name))
                        continue;

                    var t = entity.Translation(l.EntityID);
                    uow.Execute(new SaveCatalogItemTranslation
                    {
                        HolderID = entity.EntityID,
                        LanguageID = l.EntityID,
                        Name = name,
                        ShortDescription = t != null 
                            ? t.ShortDescription 
                            : String.Empty,
                        Description = t != null 
                            ? t.Description 
                            : String.Empty
                    });
                }

                var oldCategoryIDs = entity.Categories
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldCategoryIDs.Except(categoryIDs))
                {
                    uow.Execute(new UnmapCatalogCategoryFromCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in categoryIDs.Except(oldCategoryIDs))
                {
                    uow.Execute(new MapCatalogCategoryToCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                var oldAttributeIDs = entity.Attributes
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldAttributeIDs.Except(attributeIDs))
                {
                    uow.Execute(new UnmapLookupAttributeFromCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in attributeIDs.Except(oldAttributeIDs))
                {
                    uow.Execute(new MapLookupAttributeToCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                var oldGroupIDs = entity.Groups
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldGroupIDs.Except(groupIDs))
                {
                    uow.Execute(new UnmapCatalogItemGroupFromCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in groupIDs.Except(oldGroupIDs))
                {
                    uow.Execute(new MapCatalogItemGroupToCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                var oldTagIDs = entity.Tags
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldTagIDs.Except(tagIDs))
                {
                    uow.Execute(new UnmapCatalogTagFromCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in tagIDs.Except(oldTagIDs))
                {
                    uow.Execute(new MapCatalogTagToCatalogItem
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                result++;
            }
        }

        #endregion
    }

    public class ImportCatalogSuppliers : ImportOperation,
        ISecuredOperation
    {
        #region Properties

        public IEnumerable<SecurityPolicy> SecurityPolicies
        {
            get
            {
                yield return new SecurityPolicy()
                    .IsAuthenticated()
                    .HasPermission("CTLG");
            }
        }

        #endregion

        #region Utilities

        protected override void Work(IUnitOfWork uow, out int result)
        {
            result = 0;
            var languages = uow.Execute(new SearchLanguages()).Result;
            foreach(var i in Objects)
            {
                if(!i.ContainsKey("EntityID") ||
                    !i.ContainsKey("Categories") ||
                    !i.ContainsKey("Attributes") ||
                    !i.ContainsKey("Tags") ||
                    !i.ContainsKey("Managers") ||
                    !i.ContainsKey("Flags"))
                {
                    continue;
                }

                int entityID = i["EntityID"].ParseAs(0);
                var categoryIDs = i["Categories"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var attributeIDs = i["Attributes"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var tagIDs = i["Tags"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var managerIDs = i["Managers"].Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.ParseAs<Int32>());
                var flags = i["Flags"].ParseAs<CatalogSupplierFlags>();
                var entity = entityID == 0 ? null : uow.Execute(new GetCatalogSupplier
                {
                    EntityID = entityID
                }).Result;

                if(entity != null)
                {
                    entity = uow.Execute(new UpdateCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        FileGroupID = entity.FileGroup != null
                            ? entity.FileGroup.EntityID
                            : 0,
                        Flags = flags
                    }).Result;
                }
                else
                {
                    entity = uow.Execute(new CreateCatalogSupplier
                    {
                        FileGroupID = 0,
                        ManagerID = managerIDs.First(),
                        Flags = flags
                    }).Result;
                }

                foreach(var l in languages.Where(x => i.ContainsKey(x.Code)))
                {
                    string name = i[l.Code];
                    if(String.IsNullOrWhiteSpace(name))
                        continue;

                    var t = entity.Translation(l.EntityID);
                    uow.Execute(new SaveCatalogSupplierTranslation
                    {
                        HolderID = entity.EntityID,
                        LanguageID = l.EntityID,
                        Name = name,
                        ShortDescription = t != null
                            ? t.ShortDescription
                            : String.Empty,
                        Description = t != null
                            ? t.Description
                            : String.Empty
                    });
                }

                var oldCategoryIDs = entity.Categories
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldCategoryIDs.Except(categoryIDs))
                {
                    uow.Execute(new UnmapCatalogCategoryFromCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in categoryIDs.Except(oldCategoryIDs))
                {
                    uow.Execute(new MapCatalogCategoryToCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                var oldAttributeIDs = entity.Attributes
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldAttributeIDs.Except(attributeIDs))
                {
                    uow.Execute(new UnmapLookupAttributeFromCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in attributeIDs.Except(oldAttributeIDs))
                {
                    uow.Execute(new MapLookupAttributeToCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                var oldTagIDs = entity.Tags
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldTagIDs.Except(tagIDs))
                {
                    uow.Execute(new UnmapCatalogTagFromCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in tagIDs.Except(oldTagIDs))
                {
                    uow.Execute(new MapCatalogTagToCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                var oldManagerIDs = entity.Managers
                    .Select(x => x.EntityID).ToList();
                foreach(var j in oldManagerIDs.Except(managerIDs))
                {
                    uow.Execute(new UnmapCatalogManagerFromCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }
                foreach(var j in managerIDs.Except(oldManagerIDs))
                {
                    uow.Execute(new MapCatalogManagerToCatalogSupplier
                    {
                        EntityID = entity.EntityID,
                        ChildID = j
                    });
                }

                result++;
            }
        }

        #endregion
    }
}
